<template>
  <ElDialog
    title="查看位置"
    width="740px"
    class="select-map-dialog"
    v-model="dialogShow"
    :close-on-click-modal="false"
    :modal-orgend-to-body="false"
    :append-to-body="true"
    @close="cancel"
  >
    <div class="amap-box">
      <ElInput
        clearable
        id="keyword"
        v-model="tipInput"
        placeholder="关键词搜索"
        :prefix-icon="Search"
        :disabled="loading"
        v-if="showSearch"
      ></ElInput>
      <div id="custom-amap"></div>
      <div class="info-list" v-if="address">
        <div class="info-item">已选择地点：{{ address }}</div>
        <div class="info-item">地点经纬度：{{ point }}</div>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <ElButton type="primary" class="btn btn-deault" @click="cancel"
          >关闭</ElButton
        >
        <!-- <ElButton class="btn btn-plain" @click="cancel">取消</ElButton>
        <ElButton type="primary" class="btn btn-deault" @click="handelSave"
          >确定</ElButton
        > -->
      </div>
    </template>
  </ElDialog>
</template>
<script type="text/javascript">
// 必须在AMap JS加载前设置安全配置
window._AMapSecurityConfig = {
  securityJsCode: mapSetting.mapSecurity || "",
};
</script>
<script setup>
import { ref, onUnmounted, watch, computed, nextTick } from "vue";
import { ElMessage, ElInput, ElDialog, ElButton } from "element-plus";
import AMapLoader from "@amap/amap-jsapi-loader";
import { Search } from "@element-plus/icons-vue";
import { mapSetting } from "#/api/map";

const map = ref(null); // 地图对象
const address = ref(""); // 地址
const point = ref([]); // 地址对应的经纬度信息

const marker = ref(null); // 地图标记
const geocoder = ref(); // 地址解析（正向）

const tipInput = ref(""); // 检索关键字
const autoComplete = ref(null);
const placeSearch = ref(null);
// 新增
const loading = ref(false);
const error = ref();

const props = defineProps({
  data: {
    type: Object,
    default: () => ({
      defaultAddress: "",
      defaultPoint: [],
    }),
  },
  isShow: {
    type: Boolean,
    default: false,
  },
  showSearch: {  // 添加 showSearch 属性，默认为 true
    type: Boolean,
    default: true,
  },
});

const defaultPoint = computed(
  () => props.data?.defaultPoint || [116.397428, 39.90923]
);
const defaultAddress = computed(() => props.data?.defaultAddress || "");

const emits = defineEmits(["update:isShow", "getPosition"]);
const dialogShow = computed({
  get: () => props.isShow,
  set: (value) => {
    emits("update:isShow", value);
  },
});

// 监听对话框显示状态
watch(
  () => props.isShow,
  (newVal) => {
    dialogShow.value = newVal;
    if (newVal) {
      nextTick().then(initMap);
    } else {
      cleanupMap();
    }
  }
);

watch(
  () => props.data,
  (newVal) => {
    if (newVal?.defaultPoint) {
      point.value = newVal.defaultPoint;
      if (map.value) {
        map.value.setCenter(newVal.defaultPoint);
        addMarker();
      }
    }
    if (newVal?.defaultAddress) {
      address.value = newVal.defaultAddress;
      tipInput.value = newVal.defaultAddress;
    }
  },
  { deep: true, immediate: true }
);

// 添加一个响应式变量来跟踪地图是否已初始化
const isMapInitialized = ref(false);

// 修改 tipInput 的监听器，确保地图已初始化
watch(
  () => tipInput.value,
  (newVal) => {
    // 只有在地图初始化完成后才执行搜索
    if (isMapInitialized.value && newVal && placeSearch.value) {
      // 清除之前的延迟搜索（防抖）
      if (window.searchTimeout) {
        clearTimeout(window.searchTimeout);
      }
      
      // 延迟执行搜索，避免用户输入时频繁触发
      window.searchTimeout = setTimeout(() => {
        if (placeSearch.value) {
          placeSearch.value.search(newVal);
        }
      }, 500);
    } else if (isMapInitialized.value && !newVal && placeSearch.value) {
      // 如果输入为空，清空搜索结果
      placeSearch.value.clear();
    }
  }
);

// 初始化地图
// 在 initMap 函数的最后添加标记地图已初始化
const initMap = async () => {
  // 如果地图已存在或不在显示状态，则跳过
  if (map.value || !dialogShow.value) return;

  loading.value = true;
  error.value = null;

  try {
    const AMap = await AMapLoader.load({
      key: mapSetting.mapKey,
      version: "2.0",
      plugins: [
        "AMap.ToolBar",
        "AMap.Scale",
        "AMap.MapType",
        "AMap.Geolocation",
        "AMap.AutoComplete",
        "AMap.PlaceSearch",
        "AMap.Geocoder",
        "AMap.Marker",
      ],
    });
    const center = defaultPoint.value;
    address.value = defaultAddress.value;
    point.value = defaultPoint.value;

    map.value = new AMap.Map("custom-amap", {
      viewMode: "2D",
      zoom: 13,
      center,
      showIndoorMap: false,
      resizeEnable: true,
    });

    // 初始化地理编码器
    geocoder.value = new AMap.Geocoder({
      city: "010", //城市设为北京，默认："全国"
      radius: 1000, //范围，默认：500
    });

    // 添加定位控件
    const geolocation = new AMap.Geolocation({
      enableHighAccuracy: true,
      timeout: 10000,
      buttonPosition: "RB",
    });
    // 添加常用控件
    map.value.addControl(geolocation);
    map.value.addControl(new AMap.MapType());
    // 地图点击事件
    map.value.on("click", clickMapHandler);

    addMarker();

    // 搜索框自动完成类
    autoComplete.value = new AMap.AutoComplete({
      input: "keyword", // input 为绑定输入提示功能的input的DOM ID
    });
    // 构造地点查询类
    placeSearch.value = new AMap.PlaceSearch({
      map: map.value,
    });
    // 当选中某条搜索记录时触发
    autoComplete.value.on("select", selectHandler);
    // poi覆盖物点击事件
    placeSearch.value.on("markerClick", clickMarkerHandler);
    
    // 标记地图已初始化完成
    isMapInitialized.value = true;
    
    // 如果输入框已经有值，初始化时触发一次搜索
    if (tipInput.value && placeSearch.value) {
      placeSearch.value.search(tipInput.value);
    }
  } catch (err) {
    console.error("地图初始化失败:", err);
    error.value = "地图加载失败，请稍后重试";
    cleanupMap();
  } finally {
    loading.value = false;
  }
};

// 将经纬度转换为地址
const getAddress = () => {
  if (!geocoder.value) {
    console.error("地理编码器未初始化");
    return;
  }

  if (!point.value || point.value.length !== 2) {
    console.error("无效的坐标点:", point.value);
    return;
  }

  try {
    geocoder.value.getAddress(point.value, (status, result) => {
      if (status === "complete") {
        if (result?.info === "OK" && result?.regeocode) {
          address.value = result.regeocode.formattedAddress;
        } else {
          let errorMsg = "地理编码失败";
          if (result?.info === "INVALID_USER_KEY") {
            errorMsg = "高德地图API密钥无效";
          } else if (result?.info === "DAILY_QUERY_OVER_LIMIT") {
            errorMsg = "高德地图API调用已达日限额";
          }
          console.error(errorMsg, result);
          ElMessage.error(errorMsg);
        }
      } else {
        console.error("地理编码请求失败:", status, result);
        ElMessage.error("获取地址信息失败");
      }
    });
  } catch (error) {
    console.error("地理编码异常:", error);
    ElMessage.error("获取地址时发生错误");
  }
};

const clickMapHandler = (e) => {
  try {
    const lng = e.lnglat.lng;
    const lat = e.lnglat.lat;
    if (isNaN(lng) || isNaN(lat)) {
      throw new Error("无效的坐标值");
    }
    point.value = [lng, lat];
    map.value?.setCenter(point.value);
    // 增加点标记
    addMarker();
    // 获取地址
    getAddress();
  } catch (error) {
    console.error("地图点击处理失败:", error);
    ElMessage.error("无法获取当前位置信息");
  }
};

// 验证坐标有效性
const isValidCoordinate = (coord) => {
  return (
    Array.isArray(coord) &&
    coord.length === 2 &&
    !isNaN(coord[0]) &&
    !isNaN(coord[1]) &&
    Math.abs(coord[0]) <= 180 &&
    Math.abs(coord[1]) <= 90
  );
};

// 增加点标记
const addMarker = () => {
  if (!isValidCoordinate(point.value)) {
    console.error("无效的坐标点:", point.value);
    point.value = defaultPoint.value;
    if (!isValidCoordinate(point.value)) {
      point.value = [116.397428, 39.90923]; // 默认北京坐标
    }
  }

  // 清除其他icon
  if (marker.value) {
    marker.value.setMap(null);
    marker.value = null;
  }

  // 重新渲染icon
  marker.value = new AMap.Marker({
    position: point.value, // icon经纬度
    offset: new AMap.Pixel(-13, -30), // icon中心点的偏移量
    icon: new AMap.Icon({
      image:
        "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
      size: new AMap.Size(30, 40), // 图标大小
      imageSize: new AMap.Size(30, 40),
    }),
  });
  marker.value.setMap(map.value); // 设置icon
};

// 当选中某条记录时会触发
const selectHandler = (e) => {
  placeSearch.value.setCity(e.poi.adcode);
  placeSearch.value.search(e.poi.name); // 关键字查询查询
};
// 点击poi覆盖物事件
const clickMarkerHandler = (e) => {
  try {
    const lng = e.data.location.lng;
    const lat = e.data.location.lat;
    if (isNaN(lng) || isNaN(lat)) {
      throw new Error("无效的坐标值");
    }
    point.value = [lng, lat];
    getAddress();
  } catch (error) {
    console.error("POI点击处理失败:", error);
    ElMessage.error("无法获取POI位置信息");
  }
};

// 保存当前选择的地址,分发事件
const handelSave = () => {
  if (address.value && point.value.length && point.value.length > 0) {
    const infoObj = {
      address: address.value,
      point: point.value,
    };
    tipInput.value = "";
    emits("getPosition", infoObj);
  } else {
    ElMessage.error("请选择地址获取经纬度");
  }
};
const cancel = () => {
  tipInput.value = "";
  emits("getPosition", {});
};

// 清理地图资源
const cleanupMap = () => {
  if (map.value) {
    map.value.destroy();
    map.value = null;
  }
  isMapInitialized.value = false;
  // 清除可能存在的搜索定时器
  if (window.searchTimeout) {
    clearTimeout(window.searchTimeout);
    window.searchTimeout = null;
  }
};

// 组件卸载时清理
onUnmounted(cleanupMap);
// 立即执行一次初始化
if (dialogShow.value) {
  nextTick().then(initMap);
}
</script>

<style lang="scss" scoped>
.amap-box {
  padding: 5px 0 0;

  #custom-amap {
    width: 700px;
    height: 400px;
    margin-top: 10px;
    border: 1px solid #ccc;
  }

  .input-with {
    z-index: 1;
    width: 580px;
  }

  .address {
    color: #373737;
  }

  .info-list {
    padding: 5px 5px 0;
    line-height: 24px;
  }
}
</style>

<style lang="scss">
.select-map-dialog {
  .el-dialog__body {
    padding-top: 3px;
    padding-bottom: 3px;
  }
}

.amap-sug-result {
  z-index: 2024;
}
</style>
